#!/usr/bin/env bash

prog_name=$(basename "${0}")

# Usage
usage() {
    echo "Usage: ${prog_name} [ args ] [ source files ]"
    echo "args (optional):"
    echo "    --version                                    : output cppcheck version"
    echo "    --misra-addon [ misra.py file ]              : default '${MISRA_PY}'"
    echo "    --rule-texts [ rule texts file ]             : default '${RULE_TEXTS}'"
    echo "    --suppress-rules [ list of rules to ignore ] : default '${IGNORE_RULES}'"
    echo "    --cppcheck-opts [ cppcheck options ]         : pass options to cppcheck"
    echo "    --cppcheck-path [ cppcheck search path ]     : default '${CPPCHECK_PATH}'"
    echo ""
    echo "MISRA C 2012 checks on source files using cppcheck and misra.py addon."
    echo "Optionally specify plain text file with rule descriptions. The text file"
    echo "should list rules with the following structure:"
    echo ""
    echo "Rule <topic number>.<rule number>"
    echo "<category>: <text>"
    echo ""
    echo "Rule <topic number>.<rule number>"
    echo "<category>: <text>"
    echo ""
    echo "..."
    echo ""
    echo "where <topic number> and <rule number> are integers,"
    echo "<text> is the rule description, and"
    echo "<category>(optional) is 'Mandatory', 'Required', or 'Advisory'."
    echo ""
    echo "The ignore rules string is a list of comma-separated rules in format:"
    echo "<topic number>.<rule number>"
    echo ""
    echo "For example: "
    echo "    --suppress-rules 12.8,8.12"
    exit 1
}

# defaults
defaults() {
    RULE_TEXTS=
    IGNORE_RULES=
    CPPCHECK_OPTS=
    MISRA_PY=/usr/local/share/Cppcheck/addons/misra.py
    CPPCHECK_PATH=/usr/local/bin
}

#Set defaults
defaults

# Parse arguments
while [[ ${#} -ge 1 && ${1::1} == '-' ]]; do
    key="$1"
    case $key in
        '-h' | '--help' ) usage ;;
        '--version' )
            cppcheck --version
            exit
            ;;
        '--misra-addon')
            if [[ ${#} -eq 1 ]] ; then
                usage
            else
                MISRA_PY="$2"
            fi
            shift
            ;;
        '--rule-texts')
            if [[ ${#} -eq 1 ]] ; then
                usage
            else
                RULE_TEXTS="$2"
            fi
            shift
            ;;
        '--suppress-rules')
            if [[ ${#} -eq 1 ]] ; then
                usage
            else
                IGNORE_RULES="$2"
            fi
            shift
            ;;
        '--cppcheck-opts')
            if [[ ${#} -eq 1 ]] ; then
                usage
            else
                CPPCHECK_OPTS="$2"
            fi
            shift
            ;;
        '--cppcheck-path')
            if [[ ${#} -eq 1 ]] ; then
                usage
            else
                CPPCHECK_PATH="$2"
            fi
            shift
            ;;
        * )
            usage
            ;;
    esac
    shift
done

PATH=${CPPCHECK_PATH}:$PATH

misra_py_opts=''

if [[ -n "${RULE_TEXTS}" ]] ; then
    misra_py_opts="${misra_py_opts} --rule-texts ${RULE_TEXTS}"
fi

if [[ -n "${IGNORE_RULES}" ]] ; then
    misra_py_opts="${misra_py_opts} --suppress-rules ${IGNORE_RULES}"
fi

for f in "$@" ; do
    cppcheck ${CPPCHECK_OPTS} --dump "$f"
    python3 "${MISRA_PY}" ${misra_py_opts} "$f.dump"
done
